﻿using System;
using System.Collections.Generic;
using System.Text;
using ElteIk.RoboSoccer.Core;
using ElteIk.RoboSoccer.Communication;
using ElteIk.RoboSoccer.Core.Physics;

namespace ElteIk.RoboSoccer.TesterTactics
{
    /// <summary>
    /// Advenced Random Tactics means - Move, try shot to random targets, sometime the ball is the target, sometime shoot the ball in the goal.
    /// </summary>
    public class AdvencedRandomTactics : ITactics
    {
        #region Private fields

        protected RoboSoccerGame game;
        protected RoboSoccerTeam team;

        protected SimpleController[] robotControllers;

        protected int teamId;

        protected Vector2D[] targets;
        protected bool[] shotOrMoveTo;  // If true -> shot
        protected decimal[] targetSettedTimes;
        protected decimal[] targetTimeOuts;

        #endregion

        #region Lifecycle

        public AdvencedRandomTactics(int teamId)
        {
            this.teamId = teamId;
        }

        public void InitializeTactics(RoboSoccerGame game, int teamId)
        {
            this.game = game;

            if (teamId == 1)
                this.team = game.LeftTeam;
            else if (teamId == 2)
                this.team = game.RightTeam;

            // Setup robotContollers
            robotControllers = new SimpleController[team.Players.Count];
            for (int i = 0; i < team.Players.Count; ++i)
                robotControllers[i] = new SimpleController(team.Robots[i], game.Field);

            // SetUp targets
            targets = new Vector2D[team.Players.Count];
            for (int i = 0; i < team.Players.Count; ++i)
                targets[i] = team.Players[i].Position;

            // SetUp shotorMoveTo array
            shotOrMoveTo = new bool[team.Players.Count];
            for (int i = 0; i < team.Players.Count; i++)
                shotOrMoveTo[i] = false;

            // SetUp targetSettedTimes and targetTimeOuts
            targetSettedTimes = new decimal[team.Players.Count];
            targetTimeOuts = new decimal[team.Players.Count];
            for (int i = 0; i < team.Players.Count; i++)
            {
                targetSettedTimes[i] = game.Time;
                targetTimeOuts[i] = 0.1m;
            }
        }

        #endregion

        #region Public properties

        public RoboSoccerGame Game
        {
            get { return game; }
            set
            {
                game = value;
                InitializeTactics(game, teamId);
            }
        }

        #endregion

        #region Tactics

        public void Do()
        {
            if (game == null)
                return;

            // Random target choes
            Random r = new Random();
            for (int i = 0; i < team.Players.Count; i++)
            {
                if (game.Time - targetSettedTimes[i] >= targetTimeOuts[i])
                {
                    double rnd = r.NextDouble();
                    if (rnd > 0.4)
                    {
                        if (r.Next(0, 10) < 3)
                        {
                            targets[i] = game.Ball.Position * 1.1f;
                            shotOrMoveTo[i] = false;
                        }
                        else
                        {
                            targets[i] = (game.Ball.Position - team.Players[i].Position) * 1.1f;
                            shotOrMoveTo[i] = true;
                        }

                        targetTimeOuts[i] = Convert.ToDecimal(r.NextDouble() * 4.0);
                    }
                    else if (rnd > 0.1)
                    {
                        targets[i] = new Vector2D(r.Next(40, 150), r.Next(40, 130));

                        shotOrMoveTo[i] = false;

                        targetTimeOuts[i] = Convert.ToDecimal(r.NextDouble() * 2.0);
                    }
                    else
                    {
                        Goal g = game.Field.Goals[teamId - 1];
                        int t = 1;
                        if (teamId == 2) t = -1;
                        Vector2D shotTarget = new Vector2D((float)r.Next((int)g.Position.Y - (int)(g.Size / 2), (int)g.Position.Y + (int)(g.Size / 2)), g.Position.X + t * g.Depth / 2);
                        int distance = r.Next(10, 30);

                        targets[i] = (((Vector2D)(game.Ball.Position - shotTarget)).Normalized * distance) + game.Ball.Position;

                        targetTimeOuts[i] = Convert.ToDecimal(r.NextDouble() * 3.0);
                    }                

                    targetSettedTimes[i] = game.Time;
                }
            }

            for (int i = 0; i < team.Players.Count; i++)
                if (shotOrMoveTo[i])
                    robotControllers[i].PowerShot(targets[i], 10.0f);
                else
                    robotControllers[i].MoveTo(targets[i]);
        }

        #endregion
    }
}
